package com.yundou.www.wrpc.core.net;


import com.yundou.www.wrpc.core.config.ServerConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.string.LineEncoder;
import io.netty.handler.codec.string.LineSeparator;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * @author wangweiwei
 * @since 2021/7/20
 */
public class NettyServer {

    private NioEventLoopGroup boss;

    private NioEventLoopGroup work;

    private ServerBootstrap serverBootstrap ;

    private ServerConfig serverConfig;


    public NettyServer(ServerConfig serverConfig) {
        this.serverConfig = serverConfig;
    }


    public void startServer() {

        boss = new NioEventLoopGroup(1);

        work = new NioEventLoopGroup();

        serverBootstrap = new ServerBootstrap();

        serverBootstrap.group(boss , work);

        serverBootstrap.channel(NioServerSocketChannel.class);

        serverBootstrap.option(ChannelOption.SO_BACKLOG , serverConfig.getBackLog());

        serverBootstrap.childOption(ChannelOption.TCP_NODELAY , Boolean.TRUE);

        serverBootstrap.childHandler(new ChannelInitializer<Channel>() {
            @Override
            protected void initChannel(Channel channel) throws Exception {
                //第一版  全部是string  传输
                ChannelPipeline pipeline = channel.pipeline();

                ByteBuf buf = Unpooled.copiedBuffer("$".getBytes(StandardCharsets.UTF_8));
                pipeline.addLast(new DelimiterBasedFrameDecoder(1024 , buf));
                pipeline.addLast(new StringDecoder());

                pipeline.addLast(new StringEncoder());

                pipeline.addLast(new ServerBusinessHandler());

            }
        });

        try {
            ChannelFuture sync = serverBootstrap.bind(serverConfig.getPort()).sync();
            sync.addListener((ChannelFutureListener) channelFuture -> {
                if (channelFuture.isSuccess()) {
                    System.out.println(("服务启动成功，端口：" + serverConfig.getPort()));
                }
            });

            //  阻塞
            sync.channel().closeFuture();

        } catch (Exception e) {
            e.printStackTrace();
            stopServer();
        }
    }


    public void stopServer() {

        if (Objects.nonNull(boss)) {
            boss.shutdownGracefully();
        }
        if (Objects.nonNull(work)) {
            work.shutdownGracefully();
        }
        if (Objects.nonNull(boss)) {
            boss.shutdownGracefully();
        }
    }
}
